import { DocumentRegistry, DocumentWidget } from '@jupyterlab/docregistry';

import { Widget } from '@lumino/widgets';

import { MindElixirDocModel } from './mindElixirModel';

import MindElixir from 'mind-elixir';
import type { Options, MindElixirInstance, MindElixirData } from 'mind-elixir'

export class MindElixirPanel extends Widget {

    private m_context: DocumentRegistry.IContext<MindElixirDocModel>;

    private m_orgKeydownHandler: any = undefined;

    private m_filePath: string
    private m_model: MindElixirDocModel;

    private m_mindElixir: MindElixirInstance;
    private m_mindElixirDiv: HTMLDivElement;

    constructor(context: DocumentRegistry.IContext<MindElixirDocModel>) {
        super();

        this.m_context = context;

        this.m_filePath = context.path;
        this.m_model = context.model;

        let divId: string = 'jp-MindElixir-' + context.path;

        this.m_mindElixirDiv = document.createElement('div');
        this.m_mindElixirDiv.id = divId;
        this.m_mindElixirDiv.className = 'jp-MindElixir-panel-div';
        this.node.appendChild(this.m_mindElixirDiv);

        this.m_mindElixir = this.createMindElixirInst(this.m_mindElixirDiv);

        // 当上下文准备好后，初始化MindElixir
        context.ready.then(() => {
            const data = this.initMindElixirWithModel(context.model);
            this.m_mindElixir.init(data)
            this.m_mindElixir.toCenter() 

            this.watchMoreKeydownEvent();
            this.watchMindElixirDataChange();
            this.watchSharedModelChange();
            this.update()
        })
    }

    protected createMindElixirInst(mindElixirDiv: HTMLDivElement): MindElixirInstance {
        let mindOptions: Options = {
            el: mindElixirDiv, // or HTMLDivElement
            direction: MindElixir.SIDE,
            draggable: true, // default true
            contextMenu: true, // default true
            toolBar: true, // default true
            nodeMenu: true, // default true
            keypress: true, // default true
            locale: 'zh_CN', // [zh_CN,zh_TW,en,ja,pt,ru] waiting for PRs
            overflowHidden: false, // default false
            mouseSelectionButton: 0, // 0 for left button, 2 for right button, default 0
            allowUndo: false,
            // contextMenuOption: {
            //     focus: true,
            //     link: true,
            //     extend: [
            //         {
            //             name: 'Node edit',
            //             onclick: () => {
            //                 alert('extend menu')
            //             },
            //         },
            //     ],
            // }
        }

        return new MindElixir(mindOptions);
    }

    protected initMindElixirWithModel(model: MindElixirDocModel): MindElixirData {
        let modelContext = model.toString();
        if (modelContext == '') {
            let nodeTopic = this.m_filePath.split('/').pop();
            if (nodeTopic === undefined || nodeTopic === '') {
                nodeTopic = 'Untitled';
            } else {
                let nodeTopices = nodeTopic.split('.');
                nodeTopices.pop()
                nodeTopic = nodeTopices.join('.');
            }

            return MindElixir.new(nodeTopic);
        }
        return JSON.parse(modelContext) as MindElixirData;
    }

    protected watchMindElixirDataChange() {
        this.m_mindElixir.bus.addListener('operation', operation => {
            console.log(`operation - name: ${operation.name}`);
            if (operation.name === 'beginEdit') {
                return;
            }

            this.m_model.fromString(this.m_mindElixir.getDataString());
            this.m_model.dirty = true;
        })
    }

    protected watchMoreKeydownEvent() {
        this.m_orgKeydownHandler = this.m_mindElixir.map.onkeydown;

        this.m_mindElixir.map.onkeydown = async (e: KeyboardEvent) => {
            if (e.key === 's' && e.ctrlKey) {
                if (this.m_model.dirty) {
                    this.m_model.fromString(this.m_mindElixir.getDataString())
                    await this.m_context.save();
                }
                return true
            } else {
                return this.m_orgKeydownHandler(e);
            }
        }
    }

    protected watchSharedModelChange() {
        this.m_model.contentChanged.connect(this._whenSharedModelContentChanged);
    }

    private _whenSharedModelContentChanged() {
        console.log("_whenSharedModelClientChanged")
    }
}

export class MindElixirDocWidget extends DocumentWidget<MindElixirPanel, MindElixirDocModel> {
    constructor(options: DocumentWidget.IOptions<MindElixirPanel, MindElixirDocModel>) {
        super(options);
    }

    dispose(): void {
        this.content.dispose();
        super.dispose();
    }
}